#ifndef __arm_h__
#define __arm_h__

#include "types.h"

#pragma pack(push,1)
/*
The ARM instruction set formats are shown below.
 1 Cond 0 0 I Opcode   S Rn      Rd   Operand 2                 Data Processing /PSR Transfer
 2 Cond 0 0 0 0 0 0 A  S Rd      Rn      Rs      1 0 0 1 Rm     Multiply
 3 Cond 0 0 0 0 1 U A  S RdHi    RdLo    Rn      1 0 0 1 Rm     Multiply Long
 4 Cond 0 0 0 1 0 B 0  0 Rn      Rd      0 0 0 0 1 0 0 1 Rm     Single Data Swap
 5 Cond 0 0 0 1 0 0 1  0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 Rn     Branch and Exchange
 6 Cond 0 0 0 P U 0 W  L Rn      Rd      0 0 0 0 1 S H 1 Rm     Halfword Data Transfer:register offset
 7 Cond 0 0 0 P U 1 W  L Rn      Rd      Off     1 S H 1 Off    Halfword Data Transfer:immediate offset
 8 Cond 0 1 I P U B W  L Rn      Rd      Off                    Single Data Transfer
 9 Cond 0 1 1                                          1        Undefined
10 Cond 1 0 0 P U S W  L Rn      Register List                  Block Data Transfer
11 Cond 1 0 1 L Offset                                          Branch
12 Cond 1 1 0 P U N W  L Rn     CRd      CP#     Offset         Coprocessor DataTransfer
13 Cond 1 1 1 0 CPOpc    CRn    CRd      CP#      CP 0   CRm    Coprocessor DataOperation
14 Cond 1 1 1 0 CPOpc  L CRn    Rd       CP#      CP 1   CRm    Coprocessor RegisterTransfer
15 Cond 1 1 1 1 Ignored by processor                            Software Interrupt
 */



//coprocessor regtransfer
typedef struct _arm_insn_fmt15
{
	__u32 immed_24:24;
	__u32 cf:4;
	__u32 cond:4;
} ARM_INSN_FMT15;
//coprocessor regtransfer
typedef struct _arm_insn_fmt14
{
	__u16 CRm:4;
	__u16 one:1;
	__u16 opCode2:3;
	__u16 CP:4;
	__u16 Rd:4;
	__u16 CRn:4;
	__u16 L:1;
	__u16 CPOP:3;
	__u16 zero:1;
	__u16 seven:3;
	__u16 cond:4;
} ARM_INSN_FMT14;

//Coprocessor DataOperation
typedef struct _arm_insn_fmt13
{
	__u16 CRm:4;
	__u16 one:1;
	__u16 CP:3;
	__u16 CPp:4;
	__u16 CRd:4;
	__u16 CRn:4;
	__u16 CPOP:4;
	__u16 zero:1;
	__u16 seven:3;
	__u16 cond:4;
} ARM_INSN_FMT13;
//Coprocessor DataTransfer
typedef struct _arm_insn_fmt12
{
	char offset;
	__u16 CP:4;
	__u16 CRd:4;
	__u16 CRn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 N:1;
	__u16 U:1;
	__u16 P:1;
	__u16 fix:3;
	__u16 cond:4;
} ARM_INSN_FMT12;

typedef struct _arm_insn_fmt11
{
	__u32 offset:24;
	__u32 L:1;
	__u32 five:3;
	__u32 cond:4;
} ARM_INSN_FMT11;

typedef struct _arm_insn_fmt11a
{
	__i32 offset:24;
	__i32 L:1;
	__i32 five:3;
	__i32 cond:4;
} ARM_INSN_FMT11A;

typedef struct _arm_insn_fmt10
{
	__u16 reg_list;
	__u16 Rn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 S:1;
	__u16 U:1;
	__u16 P:1;
	__u16 four:3;
	__u16 cond:4;
} ARM_INSN_FMT10;

typedef struct _arm_insn_fmt10a
{
	__u16 reg_list:16;
	__u16 Rn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 S:1;
	__u16 addr_mode:2;
	__u16 four:3;
	__u16 cond:4;
} ARM_INSN_FMT10A;

typedef struct _arm_insn_fmt9
{
	__u32 rsvd:4;
	__u32 one:1;
	__u32 rsvd1:20;
	__u32 three:3;
	__u32 cond:4;
} ARM_INSN_FMT9;

typedef struct _arm_insn_fmt8
{
	__u16 Offl:12;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 B:1;
	__u16 U:1;
	__u16 P:1;
	__u16 I:1;
	__u16 one4:2;
	__u16 cond:4;
} ARM_INSN_FMT8;
typedef struct _arm_insn_fmt8a
{
	__u16 Rm:4;
	__u16 sI:1;
	__u16 sOp:2;
	__u16 shift_imm:5;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 B:1;
	__u16 U:1;
	__u16 P:1;
	__u16 I:1;
	__u16 one4:2;
	__u16 cond:4;
} ARM_INSN_FMT8A;

typedef struct _arm_insn_fmt8b
{
	__u16 Rm:4;
	__u16 sI:1;
	__u16 sOp:2;
	__u16 zero:1;
	__u16 Rs:4;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 B:1;
	__u16 U:1;
	__u16 P:1;
	__u16 I:1;
	__u16 one4:2;
	__u16 cond:4;
} ARM_INSN_FMT8B;
typedef struct _arm_insn_fmt7
{
	__u16 Offl:4;
	__u16 one1:1;
	__u16 H:1;
	__u16 S:1;
	__u16 one2:1;
	__u16 Offh:4;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 one3:1;
	__u16 U:1;
	__u16 P:1;
	__u16 zero3:3;
	__u16 cond:4;
} ARM_INSN_FMT7;

typedef struct _arm_insn_fmt6
{
	__u16 Rm:4;
	__u16 one1:1;
	__u16 H:1;
	__u16 S:1;
	__u16 one2:1;
	__u16 zero1:4;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 zero2:1;
	__u16 U:1;
	__u16 P:1;
	__u16 zero3:3;
	__u16 cond:4;
} ARM_INSN_FMT6;

typedef struct _arm_insn_fmt6a
{
	__u16 immL:4;
	__u16 one1:1;
	__u16 H:1;
	__u16 S:1;
	__u16 one2:1;
	__u16 immH:4;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 zero2:1;
	__u16 U:1;
	__u16 P:1;
	__u16 zero3:3;
	__u16 cond:4;
} ARM_INSN_FMT6A;

typedef struct _arm_insn_fmt5
{
	__u16 Rm:4;
	__u16 c1:4;
	__u16 f1:4;
	__u16 f2:4;
	__u16 f3:4;
	__u16 two:4;
	__u16 one:4;
	__u16 cond:4;
} ARM_INSN_FMT5;

typedef struct _arm_insn_fmt4
{
	__u16 Rm:4;
	__u16 c9:4;
	__u16 c0:4;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 z:2;
	__u16 B:1;
	__u16 c2:5;
	__u16 cond:4;
} ARM_INSN_FMT4;

typedef struct _arm_insn_fmt3
{
	__u16 Rm:4;
	__u16 c9:4;
	__u16 Rn:4;
	__u16 RdLo:4;
	__u16 RdHi:4;
	__u16 S:1;
	__u16 A:1;
	__u16 U:1;
	__u16 one:5;
	__u16 cond:4;
} ARM_INSN_FMT3;


typedef struct _arm_insn_fmt2
{
	__u16 Rm:4;
	__u16 c9:4;
	__u16 Rs:4;
	__u16 Rn:4;
	__u16 Rd:4;
	__u16 S:1;
	__u16 A:1;

	__u16 zero:6; 
	__u16 cond:4;
} ARM_INSN_FMT2;

typedef struct _arm_insn_fmt1
{
	__u16 operand2:8;
	__u16 rotate_imm:4;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 S:1;
	__u16 Opcode:4;
	__u16 I:1;
	__u16 dummy:2;
	__u16 cond:4;
} ARM_INSN_FMT1;

typedef struct _arm_insn_fmt1a
{
	__u16 Rm:4;
	__u16 sI:1;
	__u16 sOp:2;
	__u16 shift_imm:5;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 S:1;
	__u16 Opcode:4;
	__u16 I:1;
	__u16 dummy:2;
	__u16 cond:4;
} ARM_INSN_FMT1A;

typedef struct _arm_insn_fmt1b
{
	__u16 Rm:4;
	__u16 sI:1;
	__u16 sOp:2;
	__u16 dummy0:1;
	__u16 Rs:4;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 S:1;
	__u16 Opcode:4;
	__u16 I:1;
	__u16 dummy:2;
	__u16 cond:4;
} ARM_INSN_FMT1B;
typedef struct _arm_insn_fmt1c
{
	__i16 operand2:12;
	__i16 Rd:4;
	__i16 Rn:4;
	__i16 S:1;
	__i16 Opcode:4;
	__i16 I:1;
	__i16 dummy:2;
	__i16 cond:4;
} ARM_INSN_FMT1C;

typedef struct _arm_insn_msr_imm
{
	__u32 imm:8;
	__u32 rotate:4; 
	__u32 sbo:4;
	__u32 field:4;
	__u32 dummy2:2;
	__u32 R:1;
	__u32 I:1;
	__u32 dummy3:4;
	__u32 cond:4;
} ARM_INSN_MSR_IMM;

typedef struct _arm_insn_msr_reg
{
	__u32 Rm:4; 
	__u32 dummy0:8;
	__u32 dummy1:10;
	__u32 Pd:1;
	__u32 dummy2:2;
	__u32 I:1;
	__u32 dummy3:2;
	__u32 cond:4;
} ARM_INSN_MSR_REG;





typedef struct _arm_insn_fmt_blx2
{
	__u16 Rm:4;
	__u16 three:4;
	__u16 sb01:4;
	__u16 sb02:4;
	__u16 sb03:4;
	__u16 two:4;
	__u16 one:4;
	__u16 cond:4;
} ARM_INSN_FMT_BLX2;


typedef struct _arm_insn_fmt_clz
{
	__u16 Rm:4;
	__u16 c1:4;
	__u16 sbO1:4;
	__u16 Rd:4;
	__u16 sbO2:4;
	__u16 six:4;
	__u16 one:4; 
	__u16 cond:4;
} ARM_INSN_FMT_CLZ;


typedef struct _arm_insn_fmt0a
{
	__u16 Rm:4;
	__u16 sI:1;
	__u16 sOp:2;
	__u16 shift_imm:5;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 B:1;
	__u16 U:1;
	__u16 P:1;
	__u16 I:1;
	__u16 one4:2;
	__u16 cond:4;
} ARM_INSN_FMT0A;

typedef struct _arm_insn_fmt0b
{
	__u16 Rm:4;
	__u16 sI:1;
	__u16 sOp:2;
	__u16 zero:1;
	__u16 Rs:4;
	__u16 Rd:4;
	__u16 Rn:4;
	__u16 L:1;
	__u16 W:1;
	__u16 B:1;
	__u16 U:1;
	__u16 P:1;
	__u16 I:1;
	__u16 one4:2;
	__u16 cond:4;
} ARM_INSN_FMT0B;

typedef struct _arm_insn_swp{
        __u32 Rm:4;
        __u32 c_12:8;   // should be 00001001
        __u32 Rd:4;
        __u32 Rn:4;
        __u32 c_28:8;   // should be 00010000
        __u32 cond:4;
} ARM_INSN_SWP;
typedef union arm_insn_info
{
	__u32 code;
	__u8 byte[4];
	ARM_INSN_SWP swp;
	ARM_INSN_MSR_IMM msr_imm;
	ARM_INSN_MSR_REG msr_reg;
	ARM_INSN_FMT_BLX2 blx2;
	ARM_INSN_FMT_CLZ clz;
	ARM_INSN_FMT0A insn_fmt0a;
	ARM_INSN_FMT0B insn_fmt0b;
	ARM_INSN_FMT1A insn_fmt1a;
	ARM_INSN_FMT1B insn_fmt1b;
    ARM_INSN_FMT1C insn_fmt1c;
	ARM_INSN_FMT1 insn_fmt1;
	ARM_INSN_FMT2 insn_fmt2;
	ARM_INSN_FMT3 insn_fmt3;
	ARM_INSN_FMT4 insn_fmt4;
	ARM_INSN_FMT5 insn_fmt5;
	ARM_INSN_FMT6 insn_fmt6;
	ARM_INSN_FMT6A insn_fmt6a;
	ARM_INSN_FMT7 insn_fmt7;
	ARM_INSN_FMT8 insn_fmt8;
	ARM_INSN_FMT8A insn_fmt8a;
	ARM_INSN_FMT8B insn_fmt8b;
	ARM_INSN_FMT9 insn_fmt9;
	ARM_INSN_FMT10 insn_fmt10;
	ARM_INSN_FMT10A insn_fmt10a;
	ARM_INSN_FMT11 insn_fmt11;
	ARM_INSN_FMT11A insn_fmt11a;
	ARM_INSN_FMT12 insn_fmt12;
	ARM_INSN_FMT13 insn_fmt13;
	ARM_INSN_FMT14 insn_fmt14;
	ARM_INSN_FMT15 insn_fmt15;
} ARM_INSN_INFO;



/*
 1 0 0 0 Op   Offset5         Rs    Rd    Move shifted register
 2 0 0 0 1 1  I Op Rn/offset3 Rs    Rd    Add/subtract
 3 0 0 1 Op   Rd       Offset8            Move/compare/add/subtract immediate
 4 0 1 0 0 0  0 Op            Rs    Rd    ALU operations
 5 0 1 0 0 0  1 Op H1 H2      Rs/Hs Rd/Hd Hi register operations/branch exchange
 6 0 1 0 0 1  Rd Word8                    PC-relative load
 7 0 1 0 1 L  B 0 Ro         Rb     Rd    Load/store with register offset
 8 0 1 0 1 H  S 1 Ro         Rb     Rd    Load/store sign-extended byte/halfword
 9 0 1 1 B L  Offset5        Rb     Rd    Load/store with immediate offset
10 1 0 0 0 L  Offset5        Rb     Rd    Load/store halfword
11 1 0 0 1 L  Rd    Word8                 SP-relative load/store
12 1 0 1 0 SP Rd    Word8                 Load address
13 1 0 1 1 0  0 0 0 S SWord7              Add offset to stack pointer
14 1 0 1 1 L  1 0 R Rlist                 Push/pop registers
15 1 1 0 0 L  Rb    Rlist                 Multiple load/store
16 1 1 0 1 Cond S   offset8               Conditional branch
17 1 1 0 1 1 1 1 1  Value8                Software Interrupt
18 1 1 1 0 0 Offset11                     Unconditional branch
19 1 1 1 1 H Offset                       Long branch with link

*/


typedef struct _thumb_insn_fmt1
{
	__u16 Rd:3;
	__u16 Rs:3;
	__u16 off:5;
	__u16 op:2;
	__u16 x0:3;
} THUMB_INSN_FMT1;

typedef struct _thumb_insn_fmt2
{
	__u16 Rd:3;
	__u16 Rs:3;
	__u16 off:3;
	__u16 op:1;
	__u16 I:1;
	__u16 x3:5;
} THUMB_INSN_FMT2;


typedef struct _thumb_insn_fmt3
{
	char offset;
	__u16 Rd:3;
	__u16 op:2;
	__u16 x1:3;
} THUMB_INSN_FMT3;

typedef struct _thumb_insn_fmt4
{
	__u16 Rd:3;
	__u16 Rs:3;
	__u16 op:4;
	__u16 x10:6;
} THUMB_INSN_FMT4;

typedef struct _thumb_insn_fmt5
{
	__u16 Rd:3;
	__u16 Rs:3;
	__u16 H:2;
	__u16 op:2;
	__u16 x11:6;
} THUMB_INSN_FMT5;

typedef struct _thumb_insn_fmt6
{
	unsigned char word8;
	__u16 Rd:3;
	__u16 x9:5;
} THUMB_INSN_FMT6;

typedef struct _thumb_insn_fmt7
{
	__u16 Rd:3;
	__u16 Rb:3;
	__u16 Ro:3;
	__u16 zero:1;
	__u16 B:1;
	__u16 L:1;
	__u16 x5:4;
} THUMB_INSN_FMT7;

typedef struct _thumb_insn_fmt8
{
	__u16 Rd:3;
	__u16 Rb:3;
	__u16 Ro:3;
	__u16 one:1;
	__u16 H:1;
	__u16 S:1;
	__u16 x5:4;
} THUMB_INSN_FMT8;

typedef struct _thumb_insn_fmt9
{
	__u16 Rd:3;
	__u16 Rb:3;
	__u16 offset:5;
	__u16 L:1;
	__u16 B:1;
	__u16 x3:3;
} THUMB_INSN_FMT9;

typedef struct _thumb_insn_fmt10
{
	__u16 Rd:3;
	__u16 Rb:3;
	__u16 offset:5;
	__u16 L:1;
	__u16 x8:4;
} THUMB_INSN_FMT10;


typedef struct _thumb_insn_fmt11
{
	__u16 word8:8;
	__u16 Rd:3;
	__u16 L:1;
	__u16 x9:4;
} THUMB_INSN_FMT11;

typedef struct _thumb_insn_fmt12
{
	__u16 word8:8;
	__u16 Rd:3;
	__u16 SP:1;
	__u16 xa:4;
} THUMB_INSN_FMT12;

typedef struct _thumb_insn_fmt13
{
	 char sword;
	unsigned char xb0;
} THUMB_INSN_FMT13;

typedef struct _thumb_insn_fmt14
{
	unsigned char rlist;
	__u16 R:1;
	__u16 x2:2;
	__u16 L:1;
	__u16 xb:4;
} THUMB_INSN_FMT14;

typedef struct _thumb_insn_fmt15
{
	unsigned char rlist;
	__u16 Rb:3;
	__u16 L:1;
	__u16 xc:4;
} THUMB_INSN_FMT15;

typedef struct _thumb_insn_fmt16
{
	char offset8;
	__u16 S:1;
	__u16 cond:3;
	__u16 xd:4;
} THUMB_INSN_FMT16;

typedef struct _thumb_insn_fmt17
{
	char value;
	unsigned char xdf;
} THUMB_INSN_FMT17;

typedef struct _thumb_insn_fmt18
{
	__u16 offset11:11;
	__u16 x1c:5;
} THUMB_INSN_FMT18;

typedef struct _thumb_insn_fmt19
{
	__u16 offset:11;
	__u16 H:1;
	__u16 f:4;
} THUMB_INSN_FMT19;



typedef union thumb_insn_info
{
	__u16 code;
	__u8 byte[2];
	THUMB_INSN_FMT1 insn_fmt1;
	THUMB_INSN_FMT2 insn_fmt2;
	THUMB_INSN_FMT3 insn_fmt3;
	THUMB_INSN_FMT4 insn_fmt4;
	THUMB_INSN_FMT5 insn_fmt5;
	THUMB_INSN_FMT6 insn_fmt6;
	THUMB_INSN_FMT7 insn_fmt7;
	THUMB_INSN_FMT8 insn_fmt8;
	THUMB_INSN_FMT9 insn_fmt9;
	THUMB_INSN_FMT10 insn_fmt10;
	THUMB_INSN_FMT11 insn_fmt11;
	THUMB_INSN_FMT12 insn_fmt12;
	THUMB_INSN_FMT13 insn_fmt13;
	THUMB_INSN_FMT14 insn_fmt14;
	THUMB_INSN_FMT15 insn_fmt15;
	THUMB_INSN_FMT16 insn_fmt16;
	THUMB_INSN_FMT17 insn_fmt17;
	THUMB_INSN_FMT18 insn_fmt18;
	THUMB_INSN_FMT19 insn_fmt19;
}THUMB_INSN_INFO;
#pragma pack( pop)


typedef enum insn_id
{
	THUMB_AND, 
	THUMB_EOR,
	THUMB_LSL, 
	THUMB_LSR, 
	THUMB_ASR, 
	THUMB_ADC, 
	THUMB_SBC, 
	THUMB_ROR, 
	THUMB_TST, 
	THUMB_NEG,
	THUMB_CMP, 
	THUMB_CMN, 
 	THUMB_ORR, 
	THUMB_MUL, 
	THUMB_BIC,
	THUMB_MVN, 

	THUMB_SUB, 
	THUMB_ADD, 

	THUMB_BX, 
	THUMB_B, 
	THUMB_BL, 
	THUMB_BEQ, 
	THUMB_BNE, 
	THUMB_BCS, 
	THUMB_BCC, 
	THUMB_BMI, 
	THUMB_BPL, 
	THUMB_BVS, 
	THUMB_BVC, 
	THUMB_BHI, 
	THUMB_BLS,
	THUMB_BGE, 
	THUMB_BLT, 
	THUMB_BGT, 
	THUMB_BLE, 

	THUMB_LDMIA, 
	THUMB_LDR, 
	THUMB_LDRB, 
	THUMB_LDRH, 
	THUMB_LDSB, 
	THUMB_LDSH, 
	THUMB_MOV, 
	THUMB_POP, 
	THUMB_PUSH, 
	THUMB_STMIA, 
	THUMB_STR, 
	THUMB_STRB, 
	THUMB_STRH, 
	THUMB_SWI, 

	ARM_AND, 
	ARM_EOR, 	
	ARM_SUB, 
	ARM_RSB, 
	ARM_ADD, 
	ARM_ADC, 
	ARM_SBC,
	ARM_RSC, 
	ARM_TST, 
	ARM_TEQ, 
	ARM_CMP,
	ARM_CMN, 
	ARM_ORR, 
	ARM_MOV, 
	ARM_BIC, 
	ARM_MVN, 

	ARM_B, 
	ARM_BL, 
	ARM_BX, 
	ARM_CDP, 
	ARM_OR, 
	ARM_LDC, 
	ARM_LDM, 
	ARM_LDR, 
	ARM_LDRSB, 
	ARM_LDRSH, 
	ARM_LDRUH, 
	ARM_LDRD, 
 
	ARM_MCR, 
	ARM_MLA, 
	ARM_MRC, 
	ARM_MRS, 
	ARM_MSR, 
	ARM_PSR, 
	ARM_MUL, 
	ARM_STC, 
	ARM_STM, 
	ARM_STR, 
	ARM_STRD, 
	ARM_STRH, 
	ARM_STRB, 
	ARM_SWI, 
	ARM_SWP, 
	ARM_BLX,
	ARM_CLZ,
	ARM_UD
} INSN_ID;

typedef enum arm_cond
{
	COND_EQ,
	COND_NE,
	COND_CS,
	COND_CC,
	COND_MI,
	COND_PL,
	COND_VS,
	COND_VC,
	COND_HI,
	COND_LS,
	COND_GE,
	COND_LT,
	COND_GT,
	COND_LE
} ARM_COND;


typedef enum arm_shift_op
{
	ARM_SHIFT_LSL,
	ARM_SHIFT_LSR,
	ARM_SHIFT_ASR,
	ARM_SHIFT_ROR,
	ARM_SHIFT_RRX
}ARM_SHIFT_OP;
//
//physical registers
//
typedef enum arm_phy_reg
{
R0,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
PC,
CPSR,
//
// banked registers
//
//R0_USRSYS,
//R1_USRSYS,
//R2_USRSYS,
//R3_USRSYS,
//R4_USRSYS,
//R5_USRSYS,
//R6_USRSYS,
//R7_USRSYS,
//R8_USRSYS,
//R9_USRSYS,
//R10_USRSYS,
//R11_USRSYS,
//R12_USRSYS,
//R13_USRSYS,
//R14_USRSYS,
//PC_USRSYS,
//CPSR_USRSYS,
R13_SVC,
R14_SVC,
SPSR_SVC, 
CPSR_SVC, 
R13_ABORT,  
R14_ABORT,  
SPSR_ABORT, 
CPSR_ABORT, 
R13_UNDEF,  
R14_UNDEF,  
SPSR_UNDEF,
CPSR_UNDEF,
R13_IRQ,  
R14_IRQ,  
SPSR_IRQ, 
CPSR_IRQ, 
R8_FIQ,
R9_FIQ,
R10_FIQ,
R11_FIQ,
R12_FIQ,
R13_FIQ,
R14_FIQ,
SPSR_FIQ,
CPSR_FIQ,
MAX_REG
}ARM_PREG;






typedef enum arm_mode_val
{
MODE_USER_VAL=0x10,//user 
MODE_FIQ_VAL,      //FIQ
MODE_IRQ_VAL,      //interrupt 
MODE_SVC_VAL,      //supervisor 
MODE_ABORT_VAL=0x17,    //abort 
MODE_UNDEFINED_VAL=0x1b,//undefined 
MODE_SYSTEM_VAL=0x1f    // system
} ARM_MODE_VAL;


typedef enum arm_mode
{
MODE_USER,//user 
MODE_IRQ,      //interrupt 
MODE_FIQ,      //FIQ
MODE_SVC,      //supervisor 
MODE_ABORT,    //abort 
MODE_UNDEFINED,//undefined 
MODE_SYSTEM    // system
} ARM_MODE;



//<addressing_mode> = IA | IB | DA | DB | FD | FA | ED | EA

typedef enum arm_addressing_mode
{
ADDR_MODE_DA, 
ADDR_MODE_IA, 
ADDR_MODE_DB,
ADDR_MODE_IB,
ADDR_MODE_ED,
ADDR_MODE_EA,
ADDR_MODE_FD, 
ADDR_MODE_FA,

} ARM_ADDR_MODE;
// bits in CPSR
//31 30 29 28 27 .. 8 7 6 5 4 3 2 1 0
//N Z C V DNM/RAZ I F T M4-M0
//E Endian Load/Store 6
//A Imprecise Abort Mask 6
#define CPSR_BIT_N 31
#define CPSR_BIT_Z 30
#define CPSR_BIT_C 29
#define CPSR_BIT_V 28
#define CPSR_BIT_E 9
#define CPSR_BIT_A 8
#define CPSR_BIT_I 7
#define CPSR_BIT_F 6
#define CPSR_BIT_T 5
#define CPSR_MASK_MODE 0xf
#define CPSR_MASK_FLAGS ((1<<CPSR_BIT_N)\
	                    |(1<<CPSR_BIT_Z)\
	                    |(1<<CPSR_BIT_C)\
	                    |(1<<CPSR_BIT_V))

#define TEST_BIT(n,b) ((n)&(1<<(b)))
#define SET_BIT(n,b) (n)|=(1<<(b))
#define CLR_BIT(n,b) (n)&=~(1<<(b))

typedef struct arm_state
{
	ARM_MODE mode;
	__u32 prf[MAX_REG];// physical register file
} ARM_STATE,*PARM_STATE;

typedef enum bug_code
{
BUG_BAD_MODE,
BUG_UD
} BUG_CODE;

__inline __u32 bug(BUG_CODE bug)
{
   
	return 0;
}

#define BUG(x,l,f) bug(BUG_##x)

#define Thumb(cpsr)      TEST_BIT(cpsr,CPSR_BIT_T)
#define EnableIRQ(cpsr)  TEST_BIT(cpsr,CPSR_BIT_I)
#define EnableFIQ(cpsr)  TEST_BIT(cpsr,CPSR_BIT_F)





__inline ARM_PREG  PREG(int n,ARM_MODE mode) 
{
	int i=
       (n==13)?                                                    
	    (mode==MODE_IRQ      ? R13_IRQ:                 
		mode==MODE_FIQ      ? R13_FIQ:				   
		mode==MODE_ABORT   ? R13_ABORT:				   
		mode==MODE_SVC      ? R13_SVC:				   
		mode==MODE_UNDEFINED? R13_UNDEF:R13):	   
       (n==14)?													   
	   (mode==MODE_IRQ      ? R14_IRQ:                 
		mode==MODE_FIQ      ? R14_FIQ:				   
		mode==MODE_ABORT   ? R14_ABORT:				   
		mode==MODE_SVC      ? R14_SVC:				   
		mode==MODE_UNDEFINED? R14_UNDEF:R14):	   
		(n>7&&n<13)?											   
		(mode==MODE_FIQ      ? (R8_FIQ+n-8):n):         
		n;

	return (ARM_PREG)i;
}

#define Bank_R13(mode)                                   \
		mode==MODE_IRQ      ? R13_IRQ:					 \
		mode==MODE_FIQ      ? R13_FIQ:					 \
		mode==MODE_ABORT   ? R13_ABORT:				   \
		mode==MODE_SVC      ? R13_SVC:					 \
		mode==MODE_UNDEFINED? R13_UNDEF:R13	         \

#define Bank_R14(mode)                                   \
		mode==MODE_IRQ      ? R14_IRQ:                   \
		mode==MODE_FIQ      ? R14_FIQ:                   \
		mode==MODE_SVC      ? R14_SVC:                   \
		mode==MODE_ABORT   ? R14_ABORT:				   \
		mode==MODE_UNDEFINED? R14_UNDEF:R14          \

#define Bank_SPSR(mode)                                   \
		mode==MODE_IRQ      ? SPSR_IRQ:                   \
		mode==MODE_FIQ      ? SPSR_FIQ:                   \
		mode==MODE_SVC      ? SPSR_SVC:                   \
		mode==MODE_ABORT   ? SPSR_ABORT:				   \
		/*mode==MODE_UNDEFINED?*/ SPSR_UNDEF              \

#if 0
#define Bank_CPSR(mode)                                   \
		mode==MODE_IRQ      ? CPSR_IRQ:                   \
		mode==MODE_FIQ      ? CPSR_FIQ:                   \
		mode==MODE_SVC      ? CPSR_SVC:                   \
		mode==MODE_ABORT   ? CPSR_ABORT:				   \
		mode==MODE_UNDEFINED? CPSR_UNDEF:CPSR              \

#else
#define Bank_CPSR(mode)  CPSR
#endif
int disasm_thumb(char * buffer,THUMB_INSN_INFO insn_info,int pc);
int disasm_arm(char * buffer,ARM_INSN_INFO insn_info,int pc);
//int exec_thumb(PARM_STATE p_state,THUMB_INSN_INFO insn_info);
//int exec_arm(PARM_STATE p_state,ARM_INSN_INFO insn_info);
//void exec_irq(PARM_STATE p_state);
//void exec_fiq(PARM_STATE p_state);
//void set_cpsr(PARM_STATE p_state,__u32 v);


__u32 arm_sub(__u32 op1,__u32 op2,__u32 * p_flag);
__u32 arm_add(__u32 op1,__u32 op2,__u32 * p_flag);
__u32 arm_adc(__u32 op1,__u32 op2,__u32 * p_flag);
__u32 arm_sbc(__u32 op1,__u32 op2,__u32 * p_flag);



 typedef struct insn_exec_info
{
	unsigned long imm;  // for imm8, imm16, mask off high order bits.
}  INSN_EXEC_INFO,*PINSN_EXEC_INFO;


#pragma pack(push,1)
typedef struct _insn_basic_info
{
	bool thumb;
	unsigned int pc;
	union 
	{
		ARM_INSN_INFO arm_insn;
		THUMB_INSN_INFO thumb_insn;
	};
}INSN_BASIC_INFO,*PINSN_BASIC_INFO;


__inline int disasm(char * buffer,PINSN_BASIC_INFO p_insn)
{
	return p_insn->thumb?disasm_thumb(buffer,p_insn->thumb_insn,p_insn->pc):
		disasm_arm(buffer,p_insn->arm_insn,p_insn->pc);
}
#pragma pack(pop)

#endif  //__arm_h__